package top.lixunda.commerce.common.core.config;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import feign.Response;
import feign.codec.Decoder;
import feign.codec.Encoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;

/**
 * @author LiXunda
 * @version time:2019/10/10 16:19
 * <p>
 * 自定义Feign，防止LinkedHashMap
 */
@SuppressWarnings("Duplicates")
@Slf4j
@Component
public class FeignConfig {

    @Bean
    public Decoder feignDecoder() {
        log.debug("feignDecoder");
        HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
        ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
        SpringDecoder springDecoder = new SpringDecoder(objectFactory);
        Decoder decoder = (Response response, Type type) -> {
            log.debug("Feign Decoder 拦截处理 Response");
            // 当feign返回的header中包含Set-Cookie时表示下级服务生成了cookie
            // 同步
//            Collection<String> collection = response.headers().get(SpringSessionCookieSerializer.SET_COOKIE);
//            if (collection != null && collection.size() > 0) {
//                String cookie = new ArrayList<>(collection).get(0);
//                if (cookie != null && cookie.length() > 0) {
//                    // 缓存SET_COOKIE
//                    log.debug("缓存SET_COOKIE : {}", cookie);
//                    //通过RequestContextHolder获取本地请求，需要同时配置RequestInterceptor是RequestAttributes可继承
//                    ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//                    if (requestAttributes == null) {
//                        log.error("错误！获取ServletRequestAttributes失败，克隆请求header失败，无法进行请求参数转发！请检查RequestInterceptor拦截器是否启动！");
//                    } else {
//                        //获取本地线程绑定的请求对象
//                        HttpServletRequest request = requestAttributes.getRequest();
//                        HttpServletResponse response1 = requestAttributes.getResponse();
//                        // 缓存等待下次使用
//                        request.setAttribute(SpringSessionCookieSerializer.SET_COOKIE, cookie);
//                        if (response1 == null) {
//                            log.error("错误！获取HttpServletResponse失败");
//                        } else {
//                            response1.setHeader(SpringSessionCookieSerializer.SET_COOKIE, cookie);
//                        }
//                    }
//                }
//            }
            return springDecoder.decode(response, type);
        };
        return new ResponseEntityDecoder(decoder);
    }

    @Bean
    public Encoder feignEncoder() {
        log.debug("feignEncoder");
        HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
        ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
        return new SpringEncoder(objectFactory);
    }

    private ObjectMapper customObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        //Customize as much as you want
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
        return objectMapper;
    }

}
